home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Base / ListTemplate.cp < prev    next >
Encoding:
Text File  |  1996-02-19  |  13.4 KB  |  424 lines  |  [TEXT/CWIE]

  1.  
  2. #include "ListTemplate.h"
  3.  
  4. //
  5. // For BlockMoveData
  6. //
  7. #include <Memory.h>
  8.  
  9. //================================================================================
  10. // CLASS TAbstractListIteratorIterator
  11. //
  12. // As it says, this is an iterator class that enumerates a list of iterators.
  13. //================================================================================
  14.  
  15. class TAbstractListIteratorIterator
  16. {
  17. public:
  18.     TAbstractListIteratorIterator(TAbstractListIterator** iterList, UInt16* listSize) :
  19.         fIterList(iterList),
  20.         fListSize(listSize),
  21.         fCurrent(0),
  22.         fRemovedCurrent(false) {}
  23.     
  24.     Boolean                    More() const        { return fCurrent < *fListSize; }
  25.     TAbstractListIterator*    Current() const        { return fIterList[fCurrent]; }
  26.     void                    Next()                { if(fRemovedCurrent == false) ++fCurrent; fRemovedCurrent = false; }
  27.     void                    RemoveCurrent();
  28.     
  29. private:
  30.     TAbstractListIterator**    fIterList;
  31.     UInt16*                    fListSize;
  32.     UInt16                    fCurrent;
  33.     Boolean                    fRemovedCurrent;
  34. };
  35.  
  36. //-------------------------------------------------------------------
  37. // TAbstractListIteratorIterator::RemoveCurrent
  38. //-------------------------------------------------------------------
  39. void TAbstractListIteratorIterator::RemoveCurrent()
  40. {
  41.     SInt32 remainingItems = (*fListSize - fCurrent) - 1;
  42.     
  43.     if(remainingItems > 0)
  44.     {
  45.         BlockMove((Ptr)&fIterList[fCurrent + 1], (Ptr)&fIterList[fCurrent], sizeof(Ptr) * remainingItems);
  46.     }
  47.     --(*fListSize);
  48.     fRemovedCurrent = true;
  49. }
  50.  
  51. //================================================================================
  52. // CLASS TListStorage
  53. //================================================================================
  54.  
  55. //-------------------------------------------------------------------
  56. // TListStorage::TListStorage
  57. //-------------------------------------------------------------------
  58. TListStorage::TListStorage(const TListStorage& copyFrom) :
  59.         fListData(nil),
  60.         fItemSize(copyFrom.fItemSize),
  61.         fItemsInList(copyFrom.ItemsInList()),
  62.         fSpaceReserved(0),
  63. #if DEBUGPREEMPTIVELOCK
  64.         fReadLocks(0),
  65.         fWriteLocks(0),
  66. #endif
  67.         fIteratorList(nil),
  68.         fNumberOfIterators(0),
  69.         fIteratorListReservedSpace(0)
  70. {
  71.     copyFrom.LockForReading();
  72.     
  73.     this->InsureAdequateSpace(copyFrom.ItemsInList());
  74.     if(copyFrom.ItemsInList())
  75.         BlockMoveData(copyFrom.ItemAddress(0), this->ItemAddress(0), this->ItemsInList() * fItemSize);
  76.     
  77.     copyFrom.RelinquishReadLock();
  78. }
  79.  
  80. //-------------------------------------------------------------------
  81. // TListStorage::~TListStorage
  82. //-------------------------------------------------------------------
  83. TListStorage::~TListStorage()
  84. {
  85.     this->NotifyListDestroyed();
  86. }
  87.  
  88. //-------------------------------------------------------------------
  89. // TListStorage::Clone
  90. //-------------------------------------------------------------------
  91. TListStorage* TListStorage::Clone() const
  92. {
  93.     TListStorage* clonedList = new TListStorage(*this);
  94.         
  95.     return clonedList;
  96. }
  97.  
  98. //-------------------------------------------------------------------
  99. // TListStorage::Add
  100. //-------------------------------------------------------------------
  101. void TListStorage::Add(const char* elementAddress)
  102. {
  103.     //
  104.     // Don't lock for writing, InsertAtEnd does that.
  105.     //
  106.     this->InsertAtEnd(elementAddress);
  107. }
  108.  
  109. //-------------------------------------------------------------------
  110. // TListStorage::Remove
  111. //-------------------------------------------------------------------
  112. Boolean TListStorage::Remove(const char* elementToRemove, ListElementCompareProcPtr compareProc)
  113. {
  114.     this->LockForWriting();
  115.     SInt32 itemIndex = this->IndexOfItem(elementToRemove, compareProc);
  116.     
  117.     if(itemIndex >= 0)
  118.         this->RemoveItemAtIndex(itemIndex);
  119.  
  120.     this->RelinquishWriteLock();
  121.     
  122.     return (itemIndex >= 0);
  123. }
  124.  
  125. //-------------------------------------------------------------------
  126. // TListStorage::InsertAtBeginning
  127. //-------------------------------------------------------------------
  128. void TListStorage::InsertAtBeginning(const char* elementAddress)
  129. {
  130.     this->LockForWriting();
  131.     InsureAdequateSpace(this->ItemsInList() + 1);
  132.     if(this->ItemsInList() > 0)
  133.         BlockMoveData(this->ItemAddress(0), this->ItemAddress(1), this->ItemsInList() * fItemSize);
  134.     ++fItemsInList;
  135.     this->ReplaceItemAtIndex(0, elementAddress);
  136.     this->RelinquishWriteLock();
  137. }
  138.  
  139. //-------------------------------------------------------------------
  140. // TListStorage::InsertAtEnd
  141. //-------------------------------------------------------------------
  142. void TListStorage::InsertAtEnd(const char* elementAddress)
  143. {
  144.     this->LockForWriting();
  145.     InsureAdequateSpace(this->ItemsInList() + 1);
  146.     ++fItemsInList;
  147.     this->ReplaceItemAtIndex(fItemsInList-1, elementAddress);
  148.     this->RelinquishWriteLock();
  149. }
  150.  
  151. //-------------------------------------------------------------------
  152. // TListStorage::RemoveFromBeginning
  153. //-------------------------------------------------------------------
  154. void TListStorage::RemoveFromBeginning()
  155. {
  156.     this->LockForWriting();
  157.     this->RemoveItemAtIndex(0);
  158.     this->RelinquishWriteLock();
  159. }
  160.  
  161. //-------------------------------------------------------------------
  162. // TListStorage::RemoveFromEnd
  163. //-------------------------------------------------------------------
  164. void TListStorage::RemoveFromEnd()
  165. {
  166.     this->LockForWriting();
  167.     this->RemoveItemAtIndex(fItemsInList - 1);
  168.     this->RelinquishWriteLock();
  169. }
  170.  
  171. //-------------------------------------------------------------------
  172. // TListStorage::FirstItem
  173. //-------------------------------------------------------------------
  174. void TListStorage::FirstItem(char* copyToBuffer) const
  175. {
  176.     this->LockForReading();
  177.     this->ItemAtIndex(0, copyToBuffer);
  178.     this->RelinquishReadLock();
  179. }
  180.  
  181. //-------------------------------------------------------------------
  182. // TListStorage::LastItem
  183. //-------------------------------------------------------------------
  184. void TListStorage::LastItem(char* copyToBuffer) const
  185. {
  186.     this->LockForReading();
  187.     this->ItemAtIndex(this->ItemsInList() - 1,copyToBuffer);
  188.     this->RelinquishReadLock();
  189. }
  190.  
  191. //-------------------------------------------------------------------
  192. // TListStorage::ReverseOrderOfList
  193. //-------------------------------------------------------------------
  194. void TListStorage::ReverseOrderOfList(char* tempBuffer)
  195. {
  196.     this->LockForWriting();
  197.     SInt32 midPoint = this->ItemsInList() / 2;
  198.     for(SInt32 i=0; i<midPoint; ++i)
  199.     {
  200.         this->ItemAtIndex(i, tempBuffer);
  201.         this->ReplaceItemAtIndex(i, this->ItemAddress(fItemsInList - 1 - i));
  202.         this->ReplaceItemAtIndex(fItemsInList - 1 - i, tempBuffer);
  203.     }
  204.     this->RelinquishWriteLock();
  205. }
  206.  
  207. //-------------------------------------------------------------------
  208. // TListStorage::MakeEmpty
  209. //-------------------------------------------------------------------
  210. void TListStorage::MakeEmpty()
  211. {
  212.     this->LockForWriting();
  213.     fItemsInList = 0;
  214.     this->RelinquishWriteLock();
  215. }
  216.  
  217. //-------------------------------------------------------------------
  218. // TListStorage::LockForReading
  219. //-------------------------------------------------------------------
  220. void TListStorage::LockForReading() const
  221. {
  222. #if DEBUGPREEMPTIVELOCK
  223.     if(fWriteLocks > 0)
  224.         DebugStr("\pCalled LockForReading while write lock was on");
  225.     
  226.     ++((TListStorage*)this)->fReadLocks;
  227. #endif
  228. }
  229.  
  230. //-------------------------------------------------------------------
  231. // TListStorage::RelinquishReadLock
  232. //-------------------------------------------------------------------
  233. void TListStorage::RelinquishReadLock() const
  234. {
  235. #if DEBUGPREEMPTIVELOCK
  236.     if(fReadLocks < 1)
  237.         DebugStr("\pToo many calls to RelinquishReadLock");
  238.     
  239.     --((TListStorage*)this)->fReadLocks;
  240. #endif
  241. }
  242.  
  243. //-------------------------------------------------------------------
  244. // TListStorage::LockForWriting
  245. //-------------------------------------------------------------------
  246. void TListStorage::LockForWriting()
  247. {
  248. #if DEBUGPREEMPTIVELOCK
  249.     if(fReadLocks > 0)
  250.         DebugStr("\pCalled LockForWriting while read lock was on");
  251.     
  252.     ++fWriteLocks;
  253. #endif
  254. }
  255.  
  256. //-------------------------------------------------------------------
  257. // TListStorage::RelinquishWriteLock
  258. //-------------------------------------------------------------------
  259. void TListStorage::RelinquishWriteLock()
  260. {
  261. #if DEBUGPREEMPTIVELOCK
  262.     if(fWriteLocks < 1)
  263.         DebugStr("\pToo many calls to RelinquishWriteLock");
  264.     
  265.     --fWriteLocks;
  266. #endif
  267. }
  268.  
  269. //-------------------------------------------------------------------
  270. // TListStorage::ItemAtIndex
  271. //
  272. // Not preemptive-safe, must call LockForReading before using
  273. //-------------------------------------------------------------------
  274. void TListStorage::ItemAtIndex(SInt32 itemIndex, char* copyToBuffer) const
  275. {
  276.     if((itemIndex >= 0 ) && (itemIndex < this->ItemsInList()))
  277.         BlockMoveData(this->ItemAddress(itemIndex), copyToBuffer, fItemSize);
  278.     else
  279.         DebugStr("\pItem index out of range for get");
  280. }
  281.  
  282. //-------------------------------------------------------------------
  283. // TListStorage::ReplaceItemAtIndex
  284. //
  285. // Not preemptive-safe, must call LockForWriting before using
  286. //-------------------------------------------------------------------
  287. void TListStorage::ReplaceItemAtIndex(SInt32 itemIndex, const char* dataToReplaceWith)
  288. {
  289.     if((itemIndex >= 0 ) && (itemIndex < this->ItemsInList()))
  290.         BlockMoveData(dataToReplaceWith, this->ItemAddress(itemIndex), fItemSize);
  291.     else
  292.         DebugStr("\pItem index out of range for replace");
  293. }
  294.  
  295. //-------------------------------------------------------------------
  296. // TListStorage::IndexOfItem
  297. //
  298. // Not preemptive-safe, must call LockForReading before using, and
  299. // must not RelinquishReadLock until after index value obtained
  300. // from this routine is no longer needed.
  301. //-------------------------------------------------------------------
  302. SInt32 TListStorage::IndexOfItem(const char* elementToFind, ListElementCompareProcPtr compareProc, SInt32 indexToStartAt /*= 0*/) const
  303. {
  304.     SInt32 theItemIndex = -1;
  305.     
  306.     for(SInt32 i=indexToStartAt; i<this->ItemsInList(); ++i)
  307.     {
  308.         if((*compareProc)(elementToFind, this->ItemAddress(i)))
  309.         {
  310.             theItemIndex = i;
  311.             break;
  312.         }
  313.     }
  314.     
  315.     return theItemIndex;
  316. }
  317.  
  318. //-------------------------------------------------------------------
  319. // TListStorage::RemoveItemAtIndex
  320. //
  321. // Not preemptive-safe, must call LockForWriting before using
  322. //-------------------------------------------------------------------
  323. void TListStorage::RemoveItemAtIndex(SInt32 item)
  324. {
  325.     if((item >= 0) && (item < this->ItemsInList()))
  326.     {
  327.         if(item + 1 < this->ItemsInList())
  328.             BlockMoveData(this->ItemAddress(item + 1), this->ItemAddress(item), fItemSize * (fItemsInList - (item + 1)));
  329.         
  330.         --fItemsInList;
  331.     }
  332. }
  333.  
  334. //-------------------------------------------------------------------
  335. // TListStorage::InsureAdequateSpace
  336. //
  337. // Not preemptive-safe, must call LockForWriting before using
  338. //-------------------------------------------------------------------
  339. void TListStorage::InsureAdequateSpace(SInt32 numberOfItems)
  340. {
  341.     if(numberOfItems > fSpaceReserved)
  342.     {
  343.         SInt32 newReservedSpace = fSpaceReserved + kAllocationChunk;
  344.         char* newData = new char[newReservedSpace * fItemSize];
  345.         
  346.         if(fSpaceReserved > 0)
  347.         {
  348.             BlockMoveData(fListData, newData, fSpaceReserved * fItemSize);
  349.             delete fListData;
  350.         }
  351.         
  352.         fListData = newData;
  353.         fSpaceReserved = newReservedSpace;
  354.     }
  355. }
  356.  
  357. //-------------------------------------------------------------------
  358. // TListStorage::AddIterator
  359. //-------------------------------------------------------------------
  360. void TListStorage::AddIterator(TAbstractListIterator* newIter)
  361. {
  362.     this->InsureSpaceForIteratorList(fNumberOfIterators + 1);
  363.     
  364.     fIteratorList[fNumberOfIterators] = newIter;
  365.     ++fNumberOfIterators;
  366. }
  367.  
  368. //-------------------------------------------------------------------
  369. // TListStorage::RemoveIterator
  370. //-------------------------------------------------------------------
  371. void TListStorage::RemoveIterator(TAbstractListIterator* iterToRemove)
  372. {
  373.     for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
  374.         if(iter.Current() == iterToRemove)
  375.             iter.RemoveCurrent();
  376. }
  377.  
  378. //-------------------------------------------------------------------
  379. // TListStorage::InsureSpaceForIteratorList
  380. //-------------------------------------------------------------------
  381. void TListStorage::InsureSpaceForIteratorList(UInt16 numberOfItersNeeded)
  382. {
  383.     if(numberOfItersNeeded > fIteratorListReservedSpace)
  384.     {
  385.         UInt16 newReserveSpace = fIteratorListReservedSpace + kIterListAllocationChunk;
  386.         
  387.         TAbstractListIterator** newIterList = new TAbstractListIterator*[newReserveSpace];
  388.         if(fIteratorListReservedSpace > 0)
  389.             BlockMoveData(fIteratorList, newIterList, fIteratorListReservedSpace * sizeof(Ptr));
  390.         delete fIteratorList;
  391.         fIteratorList = newIterList;
  392.         
  393.         fIteratorListReservedSpace = newReserveSpace;
  394.     }
  395. }
  396.  
  397. //-------------------------------------------------------------------
  398. // TListStorage::NotifyItemAdded
  399. //-------------------------------------------------------------------
  400. void TListStorage::NotifyItemAdded(SInt32 indexOfNewItem)
  401. {
  402.     for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
  403.         iter.Current()->NotifyItemAdded(indexOfNewItem);
  404. }
  405.  
  406. //-------------------------------------------------------------------
  407. // TListStorage::NotifyItemRemoved
  408. //-------------------------------------------------------------------
  409. void TListStorage::NotifyItemRemoved(SInt32 indexOfItemRemoved)
  410. {
  411.     for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
  412.         iter.Current()->NotifyItemRemoved(indexOfItemRemoved);
  413. }
  414.  
  415. //-------------------------------------------------------------------
  416. // TListStorage::NotifyListDestroyed
  417. //-------------------------------------------------------------------
  418. void TListStorage::NotifyListDestroyed()
  419. {
  420.     for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
  421.         iter.Current()->NotifyListDestroyed();
  422. }
  423.  
  424.